<?php
class UserBase  {
    private $Smarty;
    private $Session;
    private $Salt;
    private $Pepper;
    private $Language;

    function __construct($smarty, $language){
        $this->DoctrineQuery = Doctrine_Query::create();
        $this->Smarty = $smarty;
        $this->Language = $language;
		$this->Session = new UserSession();
        $this->SmartyAssign();
        $this->SaltSpices();
        $this->PostTokenSet();

    }

    public function Resource($key, $arg = "") {
        return $this->Smarty->FetchFromDb($key, $this->Language, $arg);
    }

	public function Logout(){
		$this->Session->Destroy();
        $this->SmartyAssign();
		return true;
	}
 
	public function GetUserId(){    
		if($this->Session->UserLoggedIn()){
			return $this->Session->UserId();
		} else {
			return null;
		}
	}

	public function IsLoggedIn(){
        return $this->Session->UserLoggedIn();
	}

	public function GetUserName(){
		if($this->Session->UserLoggedIn()){
			return $this->Session->UserName();
		} else {
			return null;
		}
	}

	public function KeepAlive(){
		if($this->Session->UserLoggedIn()){
			$this->Session->KeepAlive();
		}
	}
	
	public function Login($name, $password){
		$name = trim($name);
		$password = trim($password);
        //echo $this->Session->GenerateHash($password, $this->Salt, $this->Pepper);

		if(!$this->UserExist($name)){
            $this->Error($this->Resource("TXT_ERROR_LOGIN_USER_NOT_EXIST", $name));
		}
        else {
            $user = $this->UserFetch($name, $password);
            if($user != null){
                if($user["visibility_id"] == 1){
                    $fullName = $user["person"]["firstname"]." ".$user["person"]["lastname"];
                    $this->Session->Regenerate();
                    $this->Session->UserName($name);
                    $this->Session->UserDisplayName($fullName);
                    $this->Session->UserId($user["id"]);
                    $this->SmartyAssign();
                    $this->Info($this->Resource("TXT_INFO_LOGIN_USER_SUCCESS", $fullName));
                    return true;
                }
                else{
                    $this->Error($this->Resource("TXT_ERROR_LOGIN_USER_IS_BLOCKED", $name));
                }
            } else {
                $this->Error($this->Resource("TXT_ERROR_LOGIN_USER_WRONG_PASSWORD", $name));
            }
        }

        $this->Session->LoginFailed();

        return false;
	}

    public function SmartyAssign(){
        $this->Smarty->assign("userLoggedIn", $this->Session->UserLoggedIn());
        $this->Smarty->assign("userId", $this->Session->UserId());
        $this->Smarty->assign("userName", $this->Session->UserName());
        $this->Smarty->assign("userDisplayName", $this->Session->UserDisplayName());
    }

    public function UserFetch($username, $password){
        $password = $this->Session->GenerateHash($password, $this->Salt, $this->Pepper);

        $resources = $this->DoctrineQuery
            ->from('Party p')
            ->select("p.id, p1.firstname, p1.lastname, p.visibility_id")
            ->leftJoin('p.person p1')
            ->where('p.username = "'.$username.'" && p.password = "'.$password.'"')
            ->fetchArray();

        if(count($resources) == 0){
            return null;
        }

        $result = current($resources);

        $this->DoctrineQuery
            ->update('Party p')
            ->set('p.lastactivitydate', "'".date('Y-m-d H:i:s')."'")
            ->where("id = ".$result["id"])
            ->execute();

        return $result;
    }

    public function UserExist($username){
        $resources = $this->DoctrineQuery
            ->from('Party p')
            ->select("p.id")
            ->where('p.username = "'.$username.'"')
            ->fetchArray();
        return (count($resources) != 0);
    }

    //region messages

    public function Warning($value = null) {
        return $this->SetMessage("WarningList", $value);
    }

    public function Info($value = null) {
        return $this->SetMessage("InfoList", $value);
    }

    public function Error($value = null) {
        return $this->SetMessage("ErrorList", $value);
    }

    private function SetMessage($key, $value = null) {
        if(!isset($this->$key) && $value == null){
            return Array();
        }

        if(isset($value)){
            $temp = isset($this->$key) ? $this->$key : Array();
            if(is_array($value)){
                foreach($value as $v){
                    $temp[] = $v;
                }
            }
            else{
                $temp[] = $value;
            }
            $this->$key = $temp;
        }

        $this->Smarty->assign($key, $this->$key);

        return $this->$key;
    }

    //endregion messages

    //region Spices

    public function SaltSpices(){
        $ss = new SystemSetting();

        $spices[] = SystemSetting::Salt;
        $spices[] = SystemSetting::Pepper;

        foreach($spices as $spice){
            $this->$spice = $ss->$spice();
            if ($this->$spice == null){
                $this->$spice = $this->Session->GenerateHash($this->GeneratePassword(), $this->GeneratePassword(), $this->GeneratePassword());
                $ss->SetValue($spice, $this->$spice);
            }
        }
    }

    public function GeneratePassword($length = 8, $strength = 8) {
        $vowels = 'aeuy';
        $consonants = 'bdghjmnpqrstvz';
        if ($strength >= 1) {
            $consonants .= 'BDGHJLMNPQRSTVWXZ';
        }
        if ($strength >= 2) {
            $vowels .= "AEUY";
        }
        if ($strength >= 4) {
            $consonants .= '23456789';
        }
        if ($strength >= 8) {
            $consonants .= '@#$%';
        }

        $password = '';
        $alt = time() % 2;
        for ($i = 0; $i < $length; $i++) {
            if ($alt == 1) {
                $password .= $consonants[(rand() % strlen($consonants))];
                $alt = 0;
            } else {
                $password .= $vowels[(rand() % strlen($vowels))];
                $alt = 1;
            }
        }
        return $password;
    }

    //endregion Spices

    //region post token

    private function PostTokenSet(){
        $this->Smarty->assign("postToken", "<input type='hidden' name='".$this->Session->PostTokenKey()."' value='".$this->Session->PostTokenValue()."' />");
    }

    public function ValidatePostToken(){
        $key = $this->Session->PostTokenKey();
        if(isset($_POST[$key])){
            $token = $_POST[$key];
            if(!$this->Session->ValidatePostToken($token, false)){
                $this->Error("Post token miss match!");
                return false;
            }
        }
        else{
            $this->Error("Post token is invalid!");
            return false;
        }
        return true;
    }

    //endregion post token
}